package com.fqxiny.aop01.aspect;

import com.fqxiny.aop01.annotation.MyCache;
import com.fqxiny.aop01.vo.UserVo;
import jakarta.annotation.Resource;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.net.ssl.SNIHostName;
import java.lang.reflect.Method;
import java.util.UUID;

/**
 * @author : 戚欣扬
 * @Description :
 */
@Aspect
@Component
public class RedisCacheAspect {
    @Resource
    private RedisTemplate<String,Object> redisTemplate;
    @Around("@annotation(myCache)")
    public Object aroud(ProceedingJoinPoint proceedingJoinPoint, MyCache myCache){

        Object[] args = proceedingJoinPoint.getArgs();

        /*SpelExpressionParser parser = new SpelExpressionParser();
        StandardEvaluationContext context = new StandardEvaluationContext();
        for (int i = 0; i < args.length; i++) {
            context.setVariable("arg" + i, args[i]);
        }
        String key = parser.parseExpression("#{arg0.id}").getValue(context, String.class);*/

        //拼接key
        String prefix = myCache.prefixKey();
        StringBuilder key = new StringBuilder(prefix);
        for (Object arg : args) {
            key.append(":"+arg.toString());
        }
        String redisKey = key.toString();
        //如果需要幂等性校验
        if(myCache.lock()){
            try {
                Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock"+ redisKey, UUID.randomUUID().toString(), myCache.expireTime(), myCache.unit());
                if(lock){
                    Object result = proceedingJoinPoint.proceed();
                    redisTemplate.opsForValue().set(redisKey,result);
                }else{
                    return null;
                }
            } catch (Throwable e) {
                throw new RuntimeException(e);
            } finally {
                redisTemplate.delete(redisKey);
            }
        }
        //如果不需要幂等性校验,一般就是查询
        Object result =  redisTemplate.opsForValue().get(redisKey);
        if(result != null ){
            return result;
        }
        //mysql
        try {
            result = proceedingJoinPoint.proceed();
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
        //if rows > 0 , write in redis
        if(result != null){
            redisTemplate.opsForValue().set(redisKey,result);
        }else{
            System.out.println("您要查询的数据不存在！");
        }
        return result;
    }
}


